-
Notifications
You must be signed in to change notification settings - Fork 78
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement parallelization options as explicit inputs. #554
Conversation
122374f
to
40aaf0e
Compare
Side note: I noticed the |
40aaf0e
to
e22998e
Compare
@sphuber this is ready for review, but not quite for merging yet. |
1a41823
to
0f92866
Compare
Aliases are taken from https://gitlab.com/QEF/q-e/-/blob/develop/Modules/command_line_options.f90#L93 The choice of which alias is used in the interface is somewhat arbitrary - now it's the one that matches the internal variable name in QE. |
0f92866
to
9a2fd50
Compare
2c1962c
to
5e43d1e
Compare
Is that a bug in |
# in QE codes. The flags that are actually implemented in a given | ||
# code should be specified in the '_ENABLED_PARALLELIZATION_FLAGS' | ||
# list of each calculation subclass. | ||
_ALLOWED_PARALLELIZATION_FLAGS = ( # yapf: disable |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Two things:
- Find the prefix "allowed" a bit weird. Why not just
_PARALLELIZATION_FLAGS
? - Why not make this a dictionary with the flag name as the key? I think you only use it in line 125 and there you transform it in a dict. Might as well define it as one then and save those lines
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah good point, will change that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done!
# bind to the name `default`, and look up its value only when the lambda is | ||
# actually called. Because `default` changes throughout the for-loop, this | ||
# would give the wrong value. | ||
extra_kwargs = {'default': partial(orm.Int, default)} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure about specifying these defaults. I think this would mean that all these calculations will now always have a bunch of int nodes as inputs even if the user doesn't specify anything. I am not sure we want this, at least not until we have proper automatic node deduplication in the database. If we still need the defaults to be set for consistency, we can maybe just do this on prepare_for_submission
of the base class, but without going through input nodes
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added these defaults mostly for caching: Two calculations could otherwise have different inputs but be functionally equivalent. They wouldn't use caching, just because the inputs are different.
I'll leave it up to you to decide if that's an important reason - I can also see the argument that the extra input nodes are unnecessary. Otherwise I can just remove the defaults.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, didn't think about the caching. Then again, maybe if we miss a cache hit because of the parallelization flags is not too bad as it should not occur too often. That reminds me though: didn't you mention somewhere that the actual defaults in QE are a bit surprising, i.e. not all 1 or something like that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The QE defaults are 1 for all inputs except ndiag
- that's why we don't have a default for that here. QE determines it based on the number of available processors and some of the other parallelization levels.
Should I remove the defaults for the other parallelization options, then?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should I remove the defaults for the other parallelization options, then?
I think you have already done this haven't you? All defaults in _PARALLELIZATION_FLAGS
are set to None
which means that required=False
will be set on the corresponding port. This means that no node will be generated unless one is passed explicitly of course, which is the behavior I was suggesting. So i think this now respects that, or am I missing something?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, I'm asking whether the code implementing defaults should also be removed. Essentially, the default is not None
code path is dead now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the default is not None code path is dead now.
Not quite. A subclass could still override _PARALLELIZATION_FLAGS
to define default for one or more flags and automatically get the spec to work correctly. Not sure if this would be useful, but could be the case. So maybe keeping the code is ok. That being said, what is this MappingProxyType
and why do you use that to create the class attribute?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, fine with me to leave it.
The MappingProxyType
is an immutable wrapper around a dictionary. If nobody has a reference to the underlying dictionary, the object as a whole is immutable (at least, unless someone goes digging deep for a way to change it).
Here I want it to be immutable because otherwise it's easy to mess up the base class by modifying _PARALLELIZATION_FLAGS
on a child class.
tests/calculations/test_pw.py
Outdated
inputs['settings'] = Dict(dict={'CMDLINE': ['-{}'.format(flag_name), '2']}) | ||
with pytest.warns(DeprecationWarning): | ||
generate_calc_job(fixture_sandbox, entry_point_name, inputs) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe still check here that the value of the settings is kept and not overridden?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done!
Thanks for the review @sphuber, I'll make the changes tomorrow. Do you think we should aim to get this into the release? |
Honestly, since this is a bit of an experiment, would it maybe make sense to not include it so that we have it in develop for some time and can get others to test it to see if they like it? |
Sure, I don't mind either way. |
I'm not sure, but I'd lean towards a yapf bug. I discovered it when adding a |
dc05900
to
63a28c5
Compare
Alright, I've addressed the comments above. One thing to still decide is whether we want to keep the ability to set defaults on the parallelization options. If not, I would remove the corresponding code. I think it's still prudent to give the parallelization options set via Note that I've removed the py3.5 test because we're targeting post-release, so I went with py3.6 compatibility only. I will rebase after we removed py3.5 compatibility. |
63a28c5
to
647581b
Compare
0c1e2ee
to
333ce3c
Compare
A few comments on my side:
|
Hm yeah, I have to admit I didn't test this. The point I was trying to make is that I'm not sure I'd get "stripping out" the explicitly passed parameters right, exactly because it's not very clear how these edge cases are handled.
No particularly strong reason. In #405 I proposed both variants. The advantage of separate inputs is that it plays nicer with defaults:
The "equivalent aliases" are handled: Only one variant is allowed, see the As far as different QE versions go: To be honest, I hadn't thought of that. But I think it wouldn't be too hard to add. Since we would still want to support "older" QE versions, at the most we will have to add new parallelization flags. We can always add a validation that checks if the used flags are compatible with the used QE version. We'd first have to introduce an input for passing the QE version, but that's the same for both variants. If there's preference for the |
@sphuber @giovannipizzi what's your preference here?
Would soon-ish be a good time to push it into |
I am planning a release soon which is need for the common workflows project. Not sure if that should stop us though. I am not sure how many people are actually working of |
I think going with the single
TLDR: I think for now we should just be conservative and make a single optional |
Alright, got it! I'll make a single |
53516e4
to
f8a6244
Compare
Alright, switched the implementation to a single |
Note to self: the (largely undocumented) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @greschd , apart from some minor requests, this is ready to be merged. I don't think we need to specify the _ENABLED_PARALLELIZATION_FLAGS
for any other plugins yet. We can check how this goes for pw.x and then apply elsewhere when needed and we figure out how it works. As for the docs, those are a bit of a mess. If you can add a section anywhere close to the PwCalculation
for now, at some point hopefully we can work on the docs with @mbercx and we will incorporate it in the correct place then
b910b7f
to
d2edbd7
Compare
Implements the parallelization options as a single `Dict` given in the `parallelization` input. If any parallelization option is specified twice (either both in `parallization` and in `settings['CMDLINE']`, or more than once in `settings['CMDLINE']`), an `InputValidationError` is raised. If the flag is given only in `settings['CMDLINE']`, an `AiidaDeprecationWarning` is issued. If any parallelization option is already specified in the `settings['CMDLINE']`, a `AiidaDeprecationWarning` is issued. The `BasePwCpInputGenerator` is given three class attributes: - `_PARALLELIZATION_FLAGS` is a mapping `{flag_name: help}` of all possible flags. - `_ENABLED_PARALLELIZATION_FLAGS` is a tuple of flag names that are implemented in a particular code. - `_PARALLELIZATION_FLAG_ALIASES` is used to detect all possible variations on a flag name. These are taken from the QE source. When checking for existing parallelization flags in the manually passed cmdline parameters, these are normalized by splitting on whitespace. QE ignores flags that are capitalized differently, so we do not have to normalize capitalization here. Currently, `_ENABLED_PARALLELIZATION_FLAGS` is set only for PW calculations. Technically it accepts the `-nimage` flag, but we disallow it because (AFAIK) it doesn't make any sense - it just repeats the same calculation. Co-authored-by: Sebastiaan Huber <mail@sphuber.net>
d2edbd7
to
a856b54
Compare
For the documentation, I just added a description to the |
Without the `__init__.py`, `pylint` thinks that `types.py` is a stand-alone module, which would shadow the `types` standard library module.
Had to add an empty |
THanks a lot @greschd |
Thanks for reviewing @sphuber! |
@sphuber I just noticed the squashed commit message for this PR is incorrect / outdated.
Specifically, we raise "if the same flag is specified through both input ports.". Just FYI, not sure if it makes sense to go back and modify the commit message - but we should probably make sure it's correct in an eventual changelog. |
So the only incorrect part is that it doesn't silently take the |
Yeah, makes sense - force-pushing to |
Fixes #405.
If any parallelization option is already specified in the
settings['CMDLINE']
, aDeprecationWarning
is issued. However, the value fromsettings['CMDLINE']
still takes precedence. This allows us to implement the defaults at the level of the inputport, without having to care about it later on.
The
BasePwCpInputGenerator
is given three class attributes:_ALLOWED_PARALLELIZATION_FLAGS
is a list of tuples (flag_name, default, help), of all possible flags_ENABLED_PARALLELIZATION_FLAGS
is a list of flag names that are implemented in a particular code._PARALLELIZATION_FLAG_ALIASES
is used to detect all possible variations on a flag name.TODO:
-nPools
) QE will simply ignore them._ENABLED_PARALLELIZATION_FLAGS
for codes other than pw.x. Help needed: I have no idea what flags other codes support.-nimage
, but I'm not sure if passing that makes any sense (a PW calculation only treats one "image"). If it doesn't, we should probably disablenimage
in thePwCalculation
. Update: Disallowed-nimage
forpw.x
for now - if there is in fact a use case, we can always re-enable it.